ウィジェットの紹介
Flutter ウィジェットは、最新のフレームワークを使用して構築されています。 からのインスピレーション反応する。中心的な考え方は、あなたが構築するということです。 UI がウィジェットから外されます。ウィジェットは自分のビューを説明します 現在の構成と状態を考慮すると、次のようになります。 ウィジェットの状態が変化すると、ウィジェットはその説明を再構築します。 フレームワークが前の説明と順番に異なっている 基礎となるレンダリングに必要な最小限の変更を決定するため ある状態から次の状態に遷移するツリー。
こんにちは世界
最小限の Flutter アプリは単にrunApp()
ウィジェットを使用した関数:
import 'package:flutter/material.dart';
void main() {
runApp(
const Center(
child: Text(
'Hello, world!',
textDirection: TextDirection.ltr,
),
),
);
}
のrunApp()
関数は指定されたものを受け取りますWidget
そしてそれをウィジェットツリーのルートにします。
この例では、ウィジェット ツリーは 2 つのウィジェットで構成されます。
のCenter
ウィジェットとその子、Text
ウィジェット。
フレームワークはルート ウィジェットに画面を強制的にカバーします。
つまり、「Hello, world」というテキストが画面の中央に配置されます。
この例では、テキストの方向を指定する必要があります。
いつ70b2b83c-3579-4a5b-bbad-33bbfee45bc1ウィジェットが使用されており、
後で説明するように、これは自動的に処理されます。
アプリを作成するときは、通常、次のような新しいウィジェットを作成します。
いずれかのサブクラスですStatelessWidget
またStatefulWidget
、
ウィジェットが状態を管理するかどうかに応じて異なります。
ウィジェットの主な仕事は、build()
関数、
これは、他の下位レベルのウィジェットに関してウィジェットを説明します。
フレームワークは、プロセスが完了するまで、これらのウィジェットを順番に構築します。
根底にあるものを表すウィジェットで底を突きますRenderObject
、
ウィジェットのジオメトリを計算して記述します。
基本的なウィジェット
Flutter には強力な基本ウィジェットのスイートが付属しています。 そのうち、以下が一般的に使用されます。
Text
- の
Text
ウィジェットを使用すると、スタイル付きのテキストを作成できます アプリケーション内で。 Row
、Column
- これらのフレックス ウィジェットを使用すると、柔軟なレイアウトを作成できます。
両方の水平(
Row
) と垂直 (Column
) 方向。 これらのオブジェクトのデザインは Web に基づいています。 フレックスボックスレイアウトモデル。 Stack
- 直線的(水平方向または垂直方向)に配置するのではなく、
ある
Stack
ウィジェットを使用すると、ペイント順にウィジェットを互いに重ねて配置できます。 その後、Positioned
の子のウィジェットStack
上、右、下を基準にして配置するには、 またはスタックの左端。スタックはウェブに基づいています 絶対位置決めレイアウトモデル。 Container
- の
Container
ウィジェットを使用すると、長方形の視覚要素を作成できます。 コンテナを装飾することができます。BoxDecoration
、 など 背景、境界線、または影。あContainer
マージンを持たせることもできますが、 パディング、およびそのサイズに適用される制約。さらに、Container
行列を使用して 3 次元空間に変換できます。
以下は、これらのウィジェットと他のウィジェットを組み合わせたいくつかの単純なウィジェットです。
import 'package:flutter/material.dart';
class MyAppBar extends StatelessWidget {
const MyAppBar({required this.title, super.key});
// Fields in a Widget subclass are always marked "final".
final Widget title;
@override
Widget build(BuildContext context) {
return Container(
height: 56, // in logical pixels
padding: const EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(color: Colors.blue[500]),
// Row is a horizontal, linear layout.
child: Row(
children: [
const IconButton(
icon: Icon(Icons.menu),
tooltip: 'Navigation menu',
onPressed: null, // null disables the button
),
// Expanded expands its child
// to fill the available space.
Expanded(
child: title,
),
const IconButton(
icon: Icon(Icons.search),
tooltip: 'Search',
onPressed: null,
),
],
),
);
}
}
class MyScaffold extends StatelessWidget {
const MyScaffold({super.key});
@override
Widget build(BuildContext context) {
// Material is a conceptual piece
// of paper on which the UI appears.
return Material(
// Column is a vertical, linear layout.
child: Column(
children: [
MyAppBar(
title: Text(
'Example title',
style: Theme.of(context) //
.primaryTextTheme
.titleLarge,
),
),
const Expanded(
child: Center(
child: Text('Hello, world!'),
),
),
],
),
);
}
}
void main() {
runApp(
const MaterialApp(
title: 'My app', // used by the OS task switcher
home: SafeArea(
child: MyScaffold(),
),
),
);
}
必ず持っておいてくださいuses-material-design: true
のエントリflutter
あなたのセクションpubspec.yaml
ファイル。事前定義されたものを使用できるようにします
のセットマテリアルアイコン。通常、この行を含めることをお勧めします
マテリアル ライブラリを使用している場合。
name: my_app
flutter:
uses-material-design: true
多くのマテリアル デザイン ウィジェットは、MaterialApp
テーマデータを引き継ぐために、正しく表示するために。
したがって、次のコマンドを使用してアプリケーションを実行します。MaterialApp
。
のMyAppBar
ウィジェットが作成するContainer
身長56
8 ピクセルの内部パディングを持つデバイスに依存しないピクセル、
左にも右にも。コンテナの中には、MyAppBar
を使用しますRow
子を整理するためのレイアウト。
真ん中の子は、title
ウィジェットは次のようにマークされていますExpanded
、
つまり、残りの利用可能なスペースを埋めるために拡張されます。
他の子供たちが食べていないもの。
複数持つことができますExpanded
子供たちと決定します
使用可能なスペースを消費する比率flex
に対する議論Expanded
。
のMyScaffold
ウィジェットはその子を垂直列に編成します。
列の先頭に次のインスタンスを配置します。MyAppBar
、
アプリバーを通過するText
タイトルとして使用するウィジェット。
ウィジェットを引数として他のウィジェットに渡すことは強力なテクニックです
これにより、幅広い用途で再利用できる汎用ウィジェットを作成できます。
さまざまな方法。ついに、MyScaffold
を使用しますExpanded
残りのスペースを本体で埋めるため、
中央に配置されたメッセージで構成されます。
詳細については、を参照してください。レイアウト。
マテリアルコンポーネントの使用
Flutter は、アプリの構築に役立つ多数のウィジェットを提供します
マテリアルデザインを踏襲したもの。マテリアル アプリは次から始まります。MaterialApp
ウィジェット: 多数の便利なウィジェットを構築します
アプリのルートに、Navigator
、
文字列で識別されるウィジェットのスタックを管理します。
「ルート」とも呼ばれます。のNavigator
スムーズに移行できます
アプリケーションの画面間。の使用MaterialApp
ウィジェットは完全にオプションですが、良い習慣となります。
import 'package:flutter/material.dart';
void main() {
runApp(
const MaterialApp(
title: 'Flutter Tutorial',
home: TutorialHome(),
),
);
}
class TutorialHome extends StatelessWidget {
const TutorialHome({super.key});
@override
Widget build(BuildContext context) {
// Scaffold is a layout for
// the major Material Components.
return Scaffold(
appBar: AppBar(
leading: const IconButton(
icon: Icon(Icons.menu),
tooltip: 'Navigation menu',
onPressed: null,
),
title: const Text('Example title'),
actions: const [
IconButton(
icon: Icon(Icons.search),
tooltip: 'Search',
onPressed: null,
),
],
),
// body is the majority of the screen.
body: const Center(
child: Text('Hello, world!'),
),
floatingActionButton: const FloatingActionButton(
tooltip: 'Add', // used by assistive technologies
onPressed: null,
child: Icon(Icons.add),
),
);
}
}
コードが から切り替わったので、MyAppBar
とMyScaffold
にAppBar
とScaffold
ウィジェット、およびからmaterial.dart
、
アプリはもう少しマテリアルっぽくなり始めています。
たとえば、アプリ バーには影があり、タイトル テキストは影を継承します。
スタイルを自動的に修正します。フローティングアクションボタンも追加されています。
ウィジェットは引数として他のウィジェットに渡されることに注意してください。
のScaffold
widget はさまざまなウィジェットを次のように受け取ります。
名前付き引数。それぞれはScaffold
適切な場所にレイアウトします。同様に、AppBar
ウィジェットを使用すると、leading
ウィジェット、およびactions
のtitle
ウィジェット。
このパターンはフレームワーク全体で繰り返し発生するものであり、
独自のウィジェットを設計するときに検討してください。
詳細については、を参照してください。マテリアルコンポーネントウィジェット。
ジェスチャーの処理
ほとんどのアプリケーションには、システムとの何らかの形式のユーザー対話が含まれています。 インタラクティブなアプリケーションを構築する最初のステップは、 入力ジェスチャー。簡単なボタンを作成して、その仕組みを確認してください。
import 'package:flutter/material.dart';
class MyButton extends StatelessWidget {
const MyButton({super.key});
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
print('MyButton was tapped!');
},
child: Container(
height: 50,
padding: const EdgeInsets.all(8),
margin: const EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.lightGreen[500],
),
child: const Center(
child: Text('Engage'),
),
),
);
}
}
void main() {
runApp(
const MaterialApp(
home: Scaffold(
body: Center(
child: MyButton(),
),
),
),
);
}
のGestureDetector
ウィジェットにはビジュアルがありません
表現ではなく、その代わりに、
ユーザー。ユーザーがタップすると、Container
、
のGestureDetector
それを呼び出しますonTap()
コールバック、この中で
コンソールにメッセージを出力する場合。使用できますGestureDetector
さまざまな入力ジェスチャを検出するため、
タップ、ドラッグ、スケールなど。
多くのウィジェットはGestureDetector
提供する
他のウィジェットのオプションのコールバック。たとえば、IconButton
、ElevatedButton
、 とFloatingActionButton
ウィジェットにはonPressed()
ユーザーがウィジェットをタップしたときにトリガーされるコールバック。
詳細については、を参照してください。Flutter のジェスチャー。
入力に応じてウィジェットを変更する
これまでのところ、このページではステートレス ウィジェットのみが使用されています。
ステートレス ウィジェットは親ウィジェットから引数を受け取ります。
彼らが保管しているものfinal
メンバー変数。
ウィジェットが要求されたときbuild()
、保存されているこれらを使用します
値を使用して、作成するウィジェットの新しい引数を取得します。
より複雑なエクスペリエンスを構築するには、たとえば、
ユーザー入力に対してより興味深い方法で反応する - アプリケーション
通常、何らかの状態を保持します。 flutterの使用法StatefulWidgets
キャプチャします
このアイデア。StatefulWidgets
生成方法を知っている特別なウィジェットですState
オブジェクトは状態を保持するために使用されます。
以下を使用して、この基本的な例を考えてみましょう。ElevatedButton
先に述べた:
import 'package:flutter/material.dart';
class Counter extends StatefulWidget {
// This class is the configuration for the state.
// It holds the values (in this case nothing) provided
// by the parent and used by the build method of the
// State. Fields in a Widget subclass are always marked
// "final".
const Counter({super.key});
@override
State<Counter> createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int _counter = 0;
void _increment() {
setState(() {
// This call to setState tells the Flutter framework
// that something has changed in this State, which
// causes it to rerun the build method below so that
// the display can reflect the updated values. If you
// change _counter without calling setState(), then
// the build method won't be called again, and so
// nothing would appear to happen.
_counter++;
});
}
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called,
// for instance, as done by the _increment method above.
// The Flutter framework has been optimized to make
// rerunning build methods fast, so that you can just
// rebuild anything that needs updating rather than
// having to individually changes instances of widgets.
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: _increment,
child: const Text('Increment'),
),
const SizedBox(width: 16),
Text('Count: $_counter'),
],
);
}
}
void main() {
runApp(
const MaterialApp(
home: Scaffold(
body: Center(
child: Counter(),
),
),
),
);
}
なぜだろうと不思議に思うかもしれませんStatefulWidget
とState
は別個のオブジェクトです。
Flutter では、これら 2 種類のオブジェクトのライフサイクルは異なります。Widgets
プレゼンテーションを構築するために使用される一時的なオブジェクトです。
アプリケーションの現在の状態。State
一方ではオブジェクト
hand、呼び出し間で永続的build()
、情報を記憶できるようになります。
上の例ではユーザー入力を受け入れ、直接使用します。
その結果build()
方法。より複雑なアプリケーションでは、
ウィジェット階層のさまざまな部分が
さまざまな懸念事項に責任を負います。たとえば、1 つ
ウィジェットは複雑なユーザー インターフェイスを表示する場合があります
具体的な情報を収集することを目的として、
日付や場所など、別のウィジェットが
その情報を使用して全体的なプレゼンテーションを変更します。
Flutter では、変更通知はウィジェットの「上」に流れます
現在の状態が流れる間、コールバックを介して階層を移動します。
プレゼンテーションを行うステートレスなウィジェットまで「ダウン」します。
このフローをリダイレクトする共通の親は、State
。
次の少し複雑な例は、その方法を示しています。
これは実際には機能します:
import 'package:flutter/material.dart';
class CounterDisplay extends StatelessWidget {
const CounterDisplay({required this.count, super.key});
final int count;
@override
Widget build(BuildContext context) {
return Text('Count: $count');
}
}
class CounterIncrementor extends StatelessWidget {
const CounterIncrementor({required this.onPressed, super.key});
final VoidCallback onPressed;
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: onPressed,
child: const Text('Increment'),
);
}
}
class Counter extends StatefulWidget {
const Counter({super.key});
@override
State<Counter> createState() => _CounterState();
}
class _CounterState extends State<Counter> {
int _counter = 0;
void _increment() {
setState(() {
++_counter;
});
}
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CounterIncrementor(onPressed: _increment),
const SizedBox(width: 16),
CounterDisplay(count: _counter),
],
);
}
}
void main() {
runApp(
const MaterialApp(
home: Scaffold(
body: Center(
child: Counter(),
),
),
),
);
}
2 つの新しいステートレス ウィジェットが作成されていることに注目してください。
~の懸念事項を明確に分離する表示するカウンタ
(CounterDisplay
) と変化カウンタ (CounterIncrementor
)。
最終的な結果は前の例と同じですが、
責任の分離により、より複雑な作業が可能になります。
個々のウィジェットにカプセル化されます。
親の単純さを維持しながら。
詳細については、以下を参照してください。
StatefulWidget
setState()
すべてをひとつにまとめる
以下は、以下をまとめたより完全な例です。
これらの概念: 架空のショッピング アプリケーションでは、さまざまな情報が表示されます。
販売されている製品を管理し、ショッピング カートを管理します。
購入予定のもの。まずプレゼンテーション クラスを定義します。ShoppingListItem
:
import 'package:flutter/material.dart';
class Product {
const Product({required this.name});
final String name;
}
typedef CartChangedCallback = Function(Product product, bool inCart);
class ShoppingListItem extends StatelessWidget {
ShoppingListItem({
required this.product,
required this.inCart,
required this.onCartChanged,
}) : super(key: ObjectKey(product));
final Product product;
final bool inCart;
final CartChangedCallback onCartChanged;
Color _getColor(BuildContext context) {
// The theme depends on the BuildContext because different
// parts of the tree can have different themes.
// The BuildContext indicates where the build is
// taking place and therefore which theme to use.
return inCart //
? Colors.black54
: Theme.of(context).primaryColor;
}
TextStyle? _getTextStyle(BuildContext context) {
if (!inCart) return null;
return const TextStyle(
color: Colors.black54,
decoration: TextDecoration.lineThrough,
);
}
@override
Widget build(BuildContext context) {
return ListTile(
onTap: () {
onCartChanged(product, inCart);
},
leading: CircleAvatar(
backgroundColor: _getColor(context),
child: Text(product.name[0]),
),
title: Text(product.name, style: _getTextStyle(context)),
);
}
}
void main() {
runApp(
MaterialApp(
home: Scaffold(
body: Center(
child: ShoppingListItem(
product: const Product(name: 'Chips'),
inCart: true,
onCartChanged: (product, inCart) {},
),
),
),
),
);
}
のShoppingListItem
ウィジェットは一般的なパターンに従います
ステートレスなウィジェットの場合。受け取った値を保存します
そのコンストラクター内でfinal
メンバー変数、
それはその後、その実行中に使用されますbuild()
関数。
たとえば、inCart
ブール値は 2 つのビジュアルを切り替えます
外観: 現在の原色を使用するもの
テーマとグレーを使用するテーマです。
ユーザーがリスト項目をタップしても、ウィジェットは変更されません
これはinCart
直接的に価値を感じます。代わりに、ウィジェットはonCartChanged
親ウィジェットから受け取った関数。
このパターンを使用すると、ウィジェットの上位に状態を保存できます
これにより、状態が長期間持続します。
極端な場合、ウィジェットに保存されている状態は次のように渡されます。runApp()
の生涯にわたって持続します
応用。
保護者が受け取ると、onCartChanged
折り返し電話、
親は内部状態を更新し、それがトリガーになります
新しいインスタンスを再構築して作成する親
のShoppingListItem
新しいものと一緒にinCart
価値。
親は新しいインスタンスを作成しますが、ShoppingListItem
再構築する場合、その操作は安価です
フレームワークは新しく構築されたウィジェットを以前のウィジェットと比較するため、
構築されたウィジェットを作成し、相違点のみを基になるウィジェットに適用します。RenderObject
。
変更可能な状態を保存する親ウィジェットの例を次に示します。
import 'package:flutter/material.dart';
class Product {
const Product({required this.name});
final String name;
}
typedef CartChangedCallback = Function(Product product, bool inCart);
class ShoppingListItem extends StatelessWidget {
ShoppingListItem({
required this.product,
required this.inCart,
required this.onCartChanged,
}) : super(key: ObjectKey(product));
final Product product;
final bool inCart;
final CartChangedCallback onCartChanged;
Color _getColor(BuildContext context) {
// The theme depends on the BuildContext because different
// parts of the tree can have different themes.
// The BuildContext indicates where the build is
// taking place and therefore which theme to use.
return inCart //
? Colors.black54
: Theme.of(context).primaryColor;
}
TextStyle? _getTextStyle(BuildContext context) {
if (!inCart) return null;
return const TextStyle(
color: Colors.black54,
decoration: TextDecoration.lineThrough,
);
}
@override
Widget build(BuildContext context) {
return ListTile(
onTap: () {
onCartChanged(product, inCart);
},
leading: CircleAvatar(
backgroundColor: _getColor(context),
child: Text(product.name[0]),
),
title: Text(
product.name,
style: _getTextStyle(context),
),
);
}
}
class ShoppingList extends StatefulWidget {
const ShoppingList({required this.products, super.key});
final List<Product> products;
// The framework calls createState the first time
// a widget appears at a given location in the tree.
// If the parent rebuilds and uses the same type of
// widget (with the same key), the framework re-uses
// the State object instead of creating a new State object.
@override
State<ShoppingList> createState() => _ShoppingListState();
}
class _ShoppingListState extends State<ShoppingList> {
final _shoppingCart = <Product>{};
void _handleCartChanged(Product product, bool inCart) {
setState(() {
// When a user changes what's in the cart, you need
// to change _shoppingCart inside a setState call to
// trigger a rebuild.
// The framework then calls build, below,
// which updates the visual appearance of the app.
if (!inCart) {
_shoppingCart.add(product);
} else {
_shoppingCart.remove(product);
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Shopping List'),
),
body: ListView(
padding: const EdgeInsets.symmetric(vertical: 8),
children: widget.products.map((product) {
return ShoppingListItem(
product: product,
inCart: _shoppingCart.contains(product),
onCartChanged: _handleCartChanged,
);
}).toList(),
),
);
}
}
void main() {
runApp(const MaterialApp(
title: 'Shopping App',
home: ShoppingList(
products: [
Product(name: 'Eggs'),
Product(name: 'Flour'),
Product(name: 'Chocolate chips'),
],
),
));
}
のShoppingList
クラスが拡張するStatefulWidget
、
つまり、このウィジェットは変更可能な状態を保存します。
ときShoppingList
ウィジェットが最初に挿入されます
ツリーに挿入すると、フレームワークはcreateState()
関数
新しいインスタンスを作成するには_ShoppingListState
それと関連付けるために
ツリー内の場所。 (サブクラスがState
通常、先頭にアンダースコアを付けて名前が付けられます
プライベート実装の詳細であることを示します)。
このウィジェットの親が再構築されると、親は新しいインスタンスを作成します
のShoppingList
ですが、フレームワークは_ShoppingListState
呼び出すのではなく、すでにツリー内にあるインスタンスcreateState
また。
現在のプロパティにアクセスするにはShoppingList
、
の_ShoppingListState
それを使用できますwidget
財産。
親が再構築して新しいものを作成する場合、ShoppingList
、
の_ShoppingListState
新しいウィジェット値で再構築します。
通知を希望する場合は、widget
プロパティの変更、
をオーバーライドするdidUpdateWidget()
渡される関数
のoldWidget
古いウィジェットと比較できるようにする
現在のウィジェット。
取り扱う際には、onCartChanged
コールバック、_ShoppingListState
に製品を追加または削除することで内部状態を変更します。_shoppingCart
。内部が変更されたことをフレームワークに通知するため
状態では、それらの呼び出しをsetState()
電話。
電話をかけるsetState
このウィジェットをダーティとしてマークし、再構築するようにスケジュールします
次回アプリが画面を更新する必要があるとき。
電話を忘れた場合setState
内部を変更する場合
ウィジェットの状態を考慮すると、フレームワークはウィジェットがどのような状態であるかを認識できません。
ダーティでウィジェットを呼び出せない可能性がありますbuild()
関数、
つまり、ユーザー インターフェイスが更新されて反映されない可能性があります。
変わった状態。このように状態を管理することで、
作成と実行のために別のコードを記述する必要はありません。
子ウィジェットを更新しています。代わりに、単に実装するだけですbuild
両方の状況を処理する関数。
ウィジェットのライフサイクル イベントへの応答
電話した後createState()
でStatefulWidget
、
フレームワークは新しい状態オブジェクトをツリーに挿入し、
それから電話しますinitState()
状態オブジェクトについて。
のサブクラスState
上書きできるinitState
仕事をする
それは一度だけ起こる必要があります。たとえば、オーバーライドしますinitState
アニメーションを設定したり、プラットフォーム サービスを購読したりできます。
の実装initState
開始するために必要です
電話することでsuper.initState
。
状態オブジェクトが不要になった場合、
フレームワークが呼び出すdispose()
状態オブジェクトについて。
オーバーライドdispose
クリーンアップ作業を行う関数。
たとえば、オーバーライドしますdispose
タイマーをキャンセルするか、
プラットフォームサービスの購読を解除します。の実装dispose
通常は電話で終わりますsuper.dispose
。
詳細については、を参照してください。State
。
キー
キーを使用してフレームワークが一致するウィジェットを制御します
ウィジェットが再構築されるときに他のウィジェットと連携します。デフォルトでは、
フレームワークは現在および以前のビルドのウィジェットと一致します
彼らによるとruntimeType
そしてそれらが現れる順番。
キーを使用する場合、フレームワークでは 2 つのウィジェットが
同じkey
同じようにruntimeType
。
キーは、多数のインスタンスを構築するウィジェットで最も役立ちます。
同じ種類のウィジェット。たとえば、ShoppingList
ウィジェット、
これで十分に構築できますShoppingListItem
インスタンスから
表示領域を塗りつぶします。
-
キーがない場合、現在のビルドの最初のエントリ 常に前のビルドの最初のエントリと同期します。 たとえ意味的には、リストの最初のエントリが 画面外にスクロールされ、ビューポートに表示されなくなります。
-
リスト内の各エントリに「セマンティック」キーを割り当てることで、 無限リストはより効率的になる可能性があります。 フレームワークは、一致するセマンティック キーを使用してエントリを同期します したがって、同様の(または同一の)視覚的外観になります。 さらに、エントリを意味的に同期するとは、 ステートフルな子ウィジェットに保持される状態はアタッチされたままになります のエントリではなく、同じセマンティック エントリに ビューポート内の同じ数値位置。
詳細については、「Key
API。
グローバルキー
グローバル キーを使用して子ウィジェットを一意に識別します。 グローバルキーは全体にわたってグローバルに一意である必要があります 必要なローカルキーとは異なり、ウィジェット階層 兄弟間でのみ一意である必要があります。なぜなら彼らはそうであるから グローバルに一意であるため、グローバル キーを使用して ウィジェットに関連付けられた状態を取得します。
詳細については、「GlobalKey
API。